<?php

Raise::load('core.RaiseObject');
Raise::load('core.reflection.RaiseVariable');
Raise::load('core.js.RaiseJavascript');

/**
 * RaiseFirebug helper class
 * Provides Debugging, logging and other function of server-side code and express the details on Firebug client-side.
 *
 * @author Sam-Mauris Yong / hellclanner at live dot com
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package phpraise.core.js
 * @since 1.2
 */
class RaiseFirebug extends RaiseObject {

    /**
     * The buffer that keeps all the Javascript code before flushing to output
     * @var string
     * @access private
     */
    private $buffer = '';

    /**
     * Timers to keep
     * @var array
     */
    private $timers = array();

    /**
     * Sets if the entire log entries are in a group
     * @var boolean
     */
    private $grouped = false;

    /**
     * Prepare for writing to Javascript
     * @param mixed $arr
     * @return string
     */
    private function prepare($arr) {
        $c = array();
        foreach ($arr as $p) {
            if (is_array($p) || is_object($p)) {
                $p = json_encode($p);
                $c[] = $p;
            } else {
                $c[] = '"' . RaiseVariable::dump($p, true, false) . '"';
            }
        }
        return $c;
    }

    /**
     * Create a new RaiseFirebug helper
     * @param string $s (optional) The group message
     */
    public function __construct($s = '') {
        if ($s) {
            $this->group('phpRaise', $s);
            $this->grouped = true;
        }
    }
    /**
     * Add a single or multiple log messages to the console.
     */
    public function dump(/* $args */) {
        $c = array();
        $argv = func_get_args();
        $c = $this->prepare($argv);
        $this->buffer .= 'console.log(' . implode(',', $c) . ');';
    }

    /**
     * Start a group with the group messages
     */
    public function group(/* $args */) {
        $c = array();
        $argv = func_get_args();
        $c = $this->prepare($argv);
        $this->buffer .= 'console.group(' . implode(',', $c) . ');';
    }

    /**
     * End a group
     */
    public function group_end() {
        $this->buffer .= 'console.groupEnd();';
    }

    /**
     * Add a single or multiple log message to the console.
     * Alias of RaiseFirebug::dump()
     */
    public function log(/* $args */) {
        $this_args = func_get_args();
        call_user_func_array(array($this, 'dump'), $this_args);
    }

    /**
     * Add a single or multiple debugging message to the console.
     */
    public function debug(/* $args */) {
        $c = array();
        $argv = func_get_args();
        $c = $this->prepare($argv);
        $this->buffer .= 'console.debug(' . implode(',', $c) . ');';
    }

    /**
     * Add a single or multiple errors to the console.
     */
    public function error(/* $args */) {
        $c = array();
        $argv = func_get_args();
        $c = $this->prepare($argv);
        $this->buffer .= 'console.error(' . implode(',', $c) . ');';
    }

    /**
     * Add a single or multiple warnings to the console.
     */
    public function warn(/* $args */) {
        $c = array();
        $argv = func_get_args();
        $c = $this->prepare($argv);
        $this->buffer .= 'console.warn(' . implode(',', $c) . ');';
    }

    /**
     * Start a new timer
     * @param string $timer_id
     */
    public function timerStart($timer_id) {
        $this->timers[$timer_id] = new RaiseTimer(true);
    }

    /**
     * Stop and return the time for a particular Timer
     * @param string $timer_id
     * @return double
     */
    public function timerStop($timer_id) {
        $result = $this->timers[$timer_id]->stop();
        $this->buffer .= 'console.log("Timer ' . $timer_id . '\nResult: ' . $result . 's");';
        unset($this->timers[$timer_id]);
        return $result;
    }

    /**
     * Return the final Javascript HTML block <script> with all the output
     * @return string
     */
    public function commit() {
        $s = RaiseJavascript::block('if(window.console && window.console.firebug){' . $this->buffer . ($this->grouped ? 'console.groupEnd();' : '') . '}else{alert("Error CE02");}');
        $this->buffer = '';
        return $s;
    }

}